package cn.itsub.sodo.audio;

import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;

import cn.itsub.sodo.util.FileUtil;


public class Sound {
 
    public static void main(String[] args) throws InterruptedException {

    	Timer timer = new Timer();
    	timer.schedule(new TimerTask() {
			public void run() {
				// TODO Auto-generated method stub
			}
		}, 0,100);
    	
    	for(int i=1;i<=10000;i++){
    		Sound pl = new Sound ();
    		pl.init(FileUtil.assetsUrl("music/QQ三国 - 战斗音乐.mp3"));
    		pl.loop(1);
    		
            Thread.sleep(100);
            System.out.println(i);
    	}
    	
        
    }
    

    private Clip clip = null;
    private int loops = 1;
    private boolean closed = false;

    public void init(String path){
        init(FileUtil.assetsUrl(path));
    }
    public void init(File file){
    	try {
    		AudioInputStream srcInput = AudioSystem.getAudioInputStream(file);
    		init(srcInput);
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }

    public void init(URL url){
        try {
            System.out.println(url);
            AudioInputStream srcInput = AudioSystem.getAudioInputStream(url);
            init(srcInput);
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }
    public void init(AudioInputStream srcInput){
        try {
            AudioInputStream audioInput = null;
            if(srcInput.getFormat().getEncoding()==Encoding.PCM_SIGNED){
                audioInput = srcInput;
            }else{
                //根据原始音频流格式创建新的PCM格式
                final AudioFormat outFormat = this.getOutFormat(srcInput.getFormat());
                audioInput = AudioSystem.getAudioInputStream(outFormat, srcInput);
            }

            DataLine.Info clipInfo = new DataLine.Info(Clip.class, audioInput.getFormat());
            this.clip = ((Clip)AudioSystem.getLine(clipInfo));
            this.clip.open(audioInput);
            this.clip.addLineListener(new LineListener() {
                public void update(LineEvent event) {
                    if(closed || isDone() ){
                        clip.close();
                    }
                }
            });
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }

    private AudioFormat getOutFormat(AudioFormat inFormat) {
        final int ch = inFormat.getChannels();
        final float rate = inFormat.getSampleRate();
        return new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, rate, 16, ch, ch * 2, rate, false);
    }
    //---------- Controller -----------
    public void start(){
    	this.clip.start();
    	
    }
    public void stop()
    {
        clip.stop();
        clip.setFramePosition(0);
    }

    public void pause()
    {
        clip.stop();
    }
    public void close(){
    	closed = true;
    	clip.close();
    	clip = null;
    }
   
    public boolean isDone(){
    	return (loops!=0 && (loops*clip.getFrameLength()==clip.getFramePosition()));
    }
    /*
     * 设置音量:0-200
     */
    public void setGain(float vol) {
        double value = vol / 100.0f;
        try {
            FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
            float db = (float)(Math.log(value==0.0?0.0001:value)/Math.log(10.0)*20.0);
            System.out.println(db);
            gainControl.setValue(db);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    /**
     * 循环次数：0代表无限循环,1代表播放1次
     * @param i
     */
    public void loop(int i)
    {
        clip.setLoopPoints(0, -1);
        clip.loop(i-1);
        this.loops = i;
    }
    public void setPosition(int frames){
    	clip.setFramePosition(frames);
    }
    public int getPosition()
    {
        return clip.getFramePosition();
    }

    public boolean isRunning()
    {
        return clip.isRunning();
    }
}
